﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using GalaSoft.MvvmLight.Command;

namespace Songhay.Wpf.Mvvm.ViewModel
{
    using Songhay.Wpf.Mvvm.Extensions;
    using Songhay.Wpf.Mvvm.View;

    /// <summary>
    /// Base class for all ViewModel classes in the application.
    /// It provides support for property change notifications 
    /// and has a DisplayName property. This class is abstract.
    /// </summary>
    public abstract class ViewModelBase : GalaSoft.MvvmLight.ViewModelBase
    {

        /// <summary>
        /// Initializes a new instance of the <see cref="ViewModelBase"/> class.
        /// </summary>
        protected ViewModelBase()
        {
            this.SetDefaultCommandActions();
        }

        #region public virtual properties:

        /// <summary>
        /// Gets the MVVM Light Client command.
        /// </summary>
        /// <value>The Client command.</value>
        public virtual RelayCommand<string> ClientCommand
        {
            get
            {
                if(_commandInput == null)
                    _commandInput = new RelayCommand<string>(p =>
                    {
                        this.DoCommand(p, this.CommandDictionary);
                    });

                return _commandInput;
            }
        }

        /// <summary>
        /// Returns the user-friendly name of this object.
        /// Child classes can set this property to a new value,
        /// or override it to determine the value on-demand.
        /// </summary>
        /// <remarks>
        /// For details on implmenting this property, see
        /// “How to: Implement Property Change Notification”
        /// http://msdn.microsoft.com/en-us/library/ms743695.aspx
        /// 
        /// A sample <c>set</c> block:
        /// <code>
        /// set
        /// {
        ///     _myProperty = value;
        ///     OnPropertyChanged("MyProperty");
        /// }
        /// </code>
        /// </remarks>
        public virtual string DisplayName { get; set; }

        /// <summary>
        /// Returns the internal name of this object
        /// for retrieval from a collection.
        /// Child classes can set this property to a new value,
        /// or override it to determine the value on-demand.
        /// </summary>
        public virtual string Name { get; set; }

        #endregion

        #region protected virtual properties:

        /// <summary>
        /// Gets or sets the command dictionary.
        /// </summary>
        /// <value>The command dictionary.</value>
        protected virtual Dictionary<string, Action> CommandDictionary { get; set; }

        /// <summary>
        /// Returns whether an exception is thrown, or if a Debug.Fail() is used
        /// when an invalid property name is passed to the VerifyPropertyName method.
        /// The default value is false, but subclasses used by unit tests might 
        /// override this property's getter to return true.
        /// </summary>
        protected virtual bool ThrowOnInvalidPropertyName { get; set; }

        #endregion

        void SetDefaultCommandActions()
        {
            var commands = new Dictionary<string, Action>();
            commands.Add("#about", () =>
            {
                var about = new AboutView();
                about.Owner = Application.Current.MainWindow;
                about.ShowDialog();
            });
            commands.Add("#exit", () => Application.Current.Shutdown(0));
            this.CommandDictionary = commands;
        }

        RelayCommand<string> _commandInput;
    }
}
